<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#7d574c">
<meta name="generator" content="Hexo 4.2.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#7d574c">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"yuanlehome.github.io","root":"/","scheme":"Pisces","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":true},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="欢迎分享，转载务必注明来源！ (https:&#x2F;&#x2F;yuanlehome.github.io&#x2F;20200612&#x2F;)  这里将要介绍的是一种在 Linux 平台实现的划词翻译工具，当然在考虑自己实现一个如此功能的工具前，本人也是在网上搜索了一些在 Linux 平台实现的类似的开源工具，例如 pdfTranslator，popup-dict，但它们的安装和配置都显得比较麻烦，而且使用起来也并不方便。 本">
<meta property="og:type" content="article">
<meta property="og:title" content="教你实现一个简易的Linux平台下的划词翻译工具">
<meta property="og:url" content="https://yuanlehome.github.io/20200612/index.html">
<meta property="og:site_name" content="LYL&#39;s Blog">
<meta property="og:description" content="欢迎分享，转载务必注明来源！ (https:&#x2F;&#x2F;yuanlehome.github.io&#x2F;20200612&#x2F;)  这里将要介绍的是一种在 Linux 平台实现的划词翻译工具，当然在考虑自己实现一个如此功能的工具前，本人也是在网上搜索了一些在 Linux 平台实现的类似的开源工具，例如 pdfTranslator，popup-dict，但它们的安装和配置都显得比较麻烦，而且使用起来也并不方便。 本">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://yuanlehome.github.io/20200612/iKnVA63lpy.gif">
<meta property="article:published_time" content="2020-06-12T13:35:42.000Z">
<meta property="article:modified_time" content="2020-06-27T12:18:58.334Z">
<meta property="article:author" content="Liu Y.L.">
<meta property="article:tag" content="划词翻译">
<meta property="article:tag" content="Linux">
<meta property="article:tag" content="shell">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://yuanlehome.github.io/20200612/iKnVA63lpy.gif">

<link rel="canonical" href="https://yuanlehome.github.io/20200612/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>教你实现一个简易的Linux平台下的划词翻译工具 | LYL's Blog</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">LYL's Blog</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-about">

    <a href="/about/" rel="section"><i class="fa fa-user fa-fw"></i>关于</a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result">
  <div id="no-result">
    <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
  </div>
</div>

    </div>
  </div>

</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://yuanlehome.github.io/20200612/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.png">
      <meta itemprop="name" content="Liu Y.L.">
      <meta itemprop="description" content="寒江孤影-江湖故人-相逢何必曾相识">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="LYL's Blog">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          教你实现一个简易的Linux平台下的划词翻译工具
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-06-12 21:35:42" itemprop="dateCreated datePublished" datetime="2020-06-12T21:35:42+08:00">2020-06-12</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">更新于</span>
                <time title="修改时间：2020-06-27 20:18:58" itemprop="dateModified" datetime="2020-06-27T20:18:58+08:00">2020-06-27</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/" itemprop="url" rel="index"><span itemprop="name">技术分享</span></a>
                </span>
            </span>

          
            <span class="post-meta-item" title="阅读次数" id="busuanzi_container_page_pv" style="display: none;">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span id="busuanzi_value_page_pv"></span>
            </span><br>
            <span class="post-meta-item" title="本文字数">
              <span class="post-meta-item-icon">
                <i class="far fa-file-word"></i>
              </span>
                <span class="post-meta-item-text">本文字数：</span>
              <span>4.4k</span>
            </span>
            <span class="post-meta-item" title="阅读时长">
              <span class="post-meta-item-icon">
                <i class="far fa-clock"></i>
              </span>
                <span class="post-meta-item-text">阅读时长 &asymp;</span>
              <span>4 分钟</span>
            </span>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <hr>
<p>欢迎分享，转载务必注明来源！</p>
<p>(<a href="https://yuanlehome.github.io/20200612/">https://yuanlehome.github.io/20200612/</a>)</p>
<hr>
<p>这里将要介绍的是一种在 <em>Linux</em> 平台实现的划词翻译工具，当然在考虑自己实现一个如此功能的工具前，本人也是在网上搜索了一些在 <em>Linux</em> 平台实现的类似的开源工具，例如 <a href="https://github.com/axipo/pdfTranslator" target="_blank" rel="noopener">pdfTranslator</a>，<a href="https://github.com/bianjp/popup-dict" target="_blank" rel="noopener">popup-dict</a>，但它们的安装和配置都显得比较麻烦，而且使用起来也并不方便。</p>
<p>本人实现这个工具的初衷本是方便自己看一些英文文献和书籍的，极为方便，考虑到分享出去可以让更多人受惠，因此这里详细介绍一下它的实现步骤。</p>
<a id="more"></a>

<p>本文所实现的划词翻译工具主要有以下特性：</p>
<ul>
<li>支持英文单词和短语到中文的翻译</li>
<li>划词翻译，终端显示</li>
<li>自动过滤选中文本中的换行等特殊字符</li>
<li>只依赖少数几个 <em>Linux</em> 命令工具</li>
</ul>
<p>下面有动图进行演示。</p>
<p><img src="iKnVA63lpy.gif" alt=""></p>
<p>本人所使用的环境是运行在 <em>VMware</em> 虚拟机下的 <em>Linux</em> 发行版 <em>Ubuntu 18.04.3 LTS</em> ，因此这里介绍的步骤可能与其他 <em>Linux</em> 发行版中的实现略有不同。下面就来一步一步的实现它吧。</p>
<h4 id="一-安装必要的命令"><a href="#一-安装必要的命令" class="headerlink" title="一. 安装必要的命令"></a>一. 安装必要的命令</h4><ol>
<li><em>xclip</em></li>
</ol>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> sudo apt install xclip</span></span><br></pre></td></tr></table></figure>

<p><em>xclip</em> 命令建立了终端和剪切板之间通道，可以用命令的方式将终端输出或文件的内容保存到剪切板中，也可以将剪切板的内容输出到终端或文件。详细的用法可以使用 <em>man xclip</em>，见其手册。这里介绍几个常用的用法。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> xclip file_name <span class="comment"># 文件内容保存到X window剪切板</span></span></span><br><span class="line"><span class="meta">$</span><span class="bash"> xclip -selection c file_name <span class="comment">#文件内容保存到外部剪切板</span></span></span><br><span class="line"><span class="meta">$</span><span class="bash"> xclip -o <span class="comment"># X window剪切板内容输出到终端显示</span></span></span><br><span class="line"><span class="meta">$</span><span class="bash"> xclip -selection c -o <span class="comment"># 外部剪切板内容输出到终端显示</span></span></span><br></pre></td></tr></table></figure>

<p>值得强调的是，这里所说的 <em>X window</em> 剪切板，简单的说就是你用鼠标选择的文本会实时的存放在这个剪切板，使用鼠标中键可以粘贴。而外部剪切板是保存你用 <em>ctrl+c</em> 复制的文本，<em>ctrl+v</em> 可以粘贴。这两个地方是不一样的。</p>
<ol start="2">
<li><em>translate-shell</em></li>
</ol>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> sudo apt install translate-shell</span></span><br></pre></td></tr></table></figure>

<p>这是命令行版的谷歌翻译工具，之前叫做 <em>Google Translate CLI</em> 是一款借助谷歌翻译（默认）、必应翻译等来翻译的命令行翻译器。它让你可以在终端访问这些翻译引擎。 <em>translate-shell</em> 在大多数 <em>Linux</em> 发行版中都能使用。常用的方法如下：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> trans en:zh [word] <span class="comment"># 英文到中文的单词翻译</span></span></span><br><span class="line"><span class="meta">$</span><span class="bash"> trans en:zh -b [text] <span class="comment"># 简要的输出，进行文本翻译</span></span></span><br></pre></td></tr></table></figure>

<p>需要注意的是，使用这个翻译工具需要你能够<strong>访问外网</strong>，或者通过修改 <em>translate-shell</em> 的默认翻译引擎，具体的方法这里就不阐述了。</p>
<h4 id="二-编程实现"><a href="#二-编程实现" class="headerlink" title="二. 编程实现"></a>二. 编程实现</h4><p>这个工具整体的思路就是 <em>C</em> 程序实时检测鼠标按键的动态，当检测到用户使用鼠标选择一段文本之后，调用 <em>shell</em> 脚本获取 <em>X window</em> 剪切板的内容进行翻译后输出到终端显示。</p>
<p><strong>1. 定位鼠标设备文件</strong></p>
<p>鼠标作为输入设备。其信息可以在文件 <em>/proc/bus/input/devices</em> 中，使用下列命令查看：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> sudo cat /proc/bus/input/devices</span></span><br><span class="line">I: Bus=0011 Vendor=0002 Product=0013 Version=0006</span><br><span class="line">N: Name="VirtualPS/2 VMware VMMouse"</span><br><span class="line">P: Phys=isa0060/serio1/input1</span><br><span class="line">S: Sysfs=/devices/platform/i8042/serio1/input/input4</span><br><span class="line">U: Uniq=</span><br><span class="line">H: Handlers=mouse0 event2 </span><br><span class="line">B: PROP=0</span><br><span class="line">B: EV=b</span><br><span class="line">B: KEY=70000 0 0 0 0</span><br><span class="line">B: ABS=3</span><br></pre></td></tr></table></figure>

<p>其中的 <em>Handlers</em> 的值 <em>event2</em> 表示可以在 <em>/dev/input/event2</em> 文件下读取鼠标的状态。需要注意的是，对于不同的设备，读取鼠标的状态的文件可能不一样，比如也可能是 <em>/dev/input/event3</em>。我们可以使用下面的命令找到你的鼠标对应的是哪一个 <em>event</em>。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> sudo cat /dev/input/event2 | hexdump <span class="comment"># 测试时改变数字即可</span></span></span><br></pre></td></tr></table></figure>

<p>比如，当我运行上面这条命令之后，我移动鼠标、按鼠标左键/中键/右键，终端都会输出一些值，这就说明 <em>event2</em> 文件就是对应着我的鼠标。如果操作鼠标没有反应，说明这个就不是。你可以通过这种方法找到你的鼠标对应的 <em>event</em> 文件。</p>
<p><strong>2. Linux 下获取按键响应</strong></p>
<p>在 <em>Linux</em> 内核中，<em>input</em> 设备用 <em>input_dev</em> 结构体描述，使用 <em>input</em> 子系统实现输入设备驱动的时候，驱动的核心工作就是向系统报告按键、触摸屏、键盘、鼠标等输入事件（<em>event*，通过 *input_event</em> 结构体描述），不再需要关心文件操作接口，因为 <em>input</em> 子系统已经完成了文件操作接口 <em>Linux/input.h</em> 这个文件定义了 <em>event</em> 事件的结构体，<em>API</em> 和标准按键的编码等。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 结构体定义见 input.h</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">input_event</span></span></span><br><span class="line"><span class="class">&#123;</span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">timeval</span> <span class="title">time</span>;</span> <span class="comment">// 按键时间</span></span><br><span class="line">    __u16 type;          <span class="comment">// 事件类型</span></span><br><span class="line">    __u16 code;          <span class="comment">// 要模拟成什么按键</span></span><br><span class="line">    __s32 value;         <span class="comment">// 是按下还是释放</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 下面宏定义见 input-event-coses.h</span></span><br><span class="line"><span class="comment">// type</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> EV_KEY 0x01</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> EV_REL 0x02</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> EV_ABS 0x03</span></span><br><span class="line"><span class="comment">// ...</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// code</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> BTN_LEFT 0x110</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> BTN_RIGHT 0x111</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> BTN_MIDDLE 0x112</span></span><br><span class="line"><span class="comment">// ...</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// value</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> MSC_SERIAL 0x00</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> MSC_PULSELED 0x01</span></span><br><span class="line"><span class="comment">// ...</span></span><br></pre></td></tr></table></figure>

<p>这里稍微介绍一下 <em>type</em>，指事件类型，常见的事件类型有：<br><em>EV_KEY</em>，按键事件，如键盘的按键（按下哪个键），鼠标的左键右键（是否击下）等；<br><em>EV_REL</em>，相对坐标，主要是指鼠标的移动事件（相对位移）；<br><em>EV_ABS</em>， 绝对坐标，主要指触摸屏的移动事件 。</p>
<p><strong>3. 编写 <em>C</em> 程序</strong></p>
<p>下面就可以编写程序来检测鼠标的动态了。首先在你的用户~目录下建立文件夹 <em>Translator*。在 *Translator</em> 里建立一个 <em>ct.c</em> 源文件，代码如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdlib.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unistd.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;linux/input.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;fcntl.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">void</span>)</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">int</span> keys_fd;</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">input_event</span> <span class="title">t</span>;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// 注意这里打开的文件根据你自己的设备情况作相应的改变</span></span><br><span class="line">    keys_fd = <span class="built_in">open</span>(<span class="string">"/dev/input/event2"</span>, O_RDONLY);</span><br><span class="line">    <span class="keyword">if</span> (keys_fd &lt;= <span class="number">0</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">"open /dev/input/event2 error!\n"</span>);</span><br><span class="line">        <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">while</span> (<span class="number">1</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">read</span>(keys_fd, &amp;t, <span class="keyword">sizeof</span>(t));</span><br><span class="line">        <span class="keyword">if</span> (t.type == EV_KEY)              <span class="comment">// 有键按下</span></span><br><span class="line">            <span class="keyword">if</span> (t.code == BTN_LEFT)        <span class="comment">// 鼠标左键</span></span><br><span class="line">                <span class="keyword">if</span> (t.value == MSC_SERIAL) <span class="comment">// 松开</span></span><br><span class="line">                    <span class="comment">// 调用外部shell脚本</span></span><br><span class="line">                    system(<span class="string">"~/Translator/goTranslate.sh"</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">close</span>(keys_fd);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>然后就是调用 <em>gcc</em> 编译器生成可执行文件 <em>ct</em>：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> gcc ct.c -o ct</span></span><br></pre></td></tr></table></figure>

<p><strong>4. 编写 <em>shell</em> 脚本翻译剪切板内容</strong></p>
<p>在 <em>Translator</em> 里建立 <em>goTranslate.sh</em> 文件，内容如下：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span><span class="bash">!/bin/bash</span></span><br><span class="line"></span><br><span class="line">str_old=$(cat ~/Translator/lastContent)</span><br><span class="line">str_new=$(xclip -o 2&gt;/dev/null | xargs)</span><br><span class="line">if [[ "$str_new" != "$str_old" &amp;&amp; $str_new ]]; then</span><br><span class="line">    echo -e "\n"</span><br><span class="line">    count=$(echo "$str_new" | wc -w)</span><br><span class="line">    if [ "$count" == "1" ]; then</span><br><span class="line">        echo -n -e "$str_new " &gt;&gt;~/Translator/words</span><br><span class="line">        echo "$str_new" | trans :zh-CN | tail -1 | cut -c 5- | sed "s,\x1b\[[0-9;]*[a-zA-Z],,g" | tee -a ~/Translator/words</span><br><span class="line">    else</span><br><span class="line">        echo "$str_new" | trans :zh-CN -b</span><br><span class="line">    fi</span><br><span class="line">    echo "$str_new" &gt;~/Translator/lastContent</span><br><span class="line">fi</span><br></pre></td></tr></table></figure>

<p>原理非常简单，读者自行了解。这里我们还要在 <em>Translator</em> 里建立一个 <em>lastContent.txt</em> 文件作为缓存，目的是本次调用脚本时能够获取上一次调用时翻译的文本内容，如果和本次调用的翻译文本一样，则本次就不进行翻译。</p>
<p><em>*5. 设置 *ct</em> 别名 **</p>
<p>这里已经可以通过下面的命令运行程序了：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> sudo ~/Translator/ct</span></span><br></pre></td></tr></table></figure>

<p>但是由于每次运行都要输出这么长的命令，因此我们在 <em>~/.bashrc</em> 文件中加入下面一条命令。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">alias ct='sudo ~/Translator/ct'</span><br></pre></td></tr></table></figure>

<p>这样，以后每次看英文文献时就可以在命令行下输入：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">$</span><span class="bash"> ct</span></span><br></pre></td></tr></table></figure>



<h4 id="三-结束语"><a href="#三-结束语" class="headerlink" title="三. 结束语"></a>三. 结束语</h4><p>这里有一些小技巧。可以更方便的使用这个工具。比如，把终端设为置顶并缩小到合适的尺寸，这样在阅读文献划词翻译时终端屏幕不会遮挡我们的视线。</p>
<p>值得说明的是，由于本人完全是为了方便自己的使用，而且在搞出这么个工具时仅仅接触 <em>Linux</em> 系统才不到两周，所以里面的实现对于有经验的朋友来说略显的有些笨拙了，请理解哈。</p>
<p>个人觉得这个工具使用起来还是很方便的，你觉得呢？</p>
<p>参考文章：</p>
<ol>
<li><a href="https://blog.csdn.net/liang12360640/article/details/50350648" target="_blank" rel="noopener">https://blog.csdn.net/liang12360640/article/details/50350648</a></li>
<li><a href="https://www.cnblogs.com/yangwindsor/articles/3454955.html" target="_blank" rel="noopener">https://www.cnblogs.com/yangwindsor/articles/3454955.html</a></li>
<li><a href="https://blog.csdn.net/liang12360640/article/details/50s350648" target="_blank" rel="noopener">https://blog.csdn.net/liang12360640/article/details/50s350648</a></li>
</ol>

    </div>

    
    
    

      <footer class="post-footer">
          <div class="post-tags">
              <a href="/tags/%E5%88%92%E8%AF%8D%E7%BF%BB%E8%AF%91/" rel="tag"># 划词翻译</a>
              <a href="/tags/Linux/" rel="tag"># Linux</a>
              <a href="/tags/shell/" rel="tag"># shell</a>
          </div>

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/20200404/" rel="prev" title="数据结构与算法之概论">
      <i class="fa fa-chevron-left"></i> 数据结构与算法之概论
    </a></div>
      <div class="post-nav-item">
    <a href="/20200614/" rel="next" title="教你用python实现一个在windows平台的定时更换壁纸的工具">
      教你用python实现一个在windows平台的定时更换壁纸的工具 <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          
    
  <div class="comments">
    <div id="lv-container" data-id="city" data-uid="MTAyMC80OTQ0NS8yNTkzNw=="></div>
  </div>
  

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-4"><a class="nav-link" href="#一-安装必要的命令"><span class="nav-number">1.</span> <span class="nav-text">一. 安装必要的命令</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#二-编程实现"><span class="nav-number">2.</span> <span class="nav-text">二. 编程实现</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#三-结束语"><span class="nav-number">3.</span> <span class="nav-text">三. 结束语</span></a></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Liu Y.L."
      src="/images/avatar.png">
  <p class="site-author-name" itemprop="name">Liu Y.L.</p>
  <div class="site-description" itemprop="description">寒江孤影-江湖故人-相逢何必曾相识</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">3</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
          
        <span class="site-state-item-count">3</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
          
        <span class="site-state-item-count">7</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/yuanlehome" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;yuanlehome" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:yuanlehome@163.com" title="E-Mail → mailto:yuanlehome@163.com" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
  </div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Liu Y.L.</span>
</div>

<span>我已在此等候你 <span id="showDays"></span></span>
<script>
  var seconds = 1000;
  var minutes = seconds * 60;
  var hours = minutes * 60;
  var days = hours * 24;
  var years = days * 365;
  var birthDay = Date.UTC(2020,04,04,00,00,00); // 这里设置建站时间
  setInterval(function() {
    var today = new Date();
    var todayYear = today.getFullYear();
    var todayMonth = today.getMonth()+1;
    var todayDate = today.getDate();
    var todayHour = today.getHours();
    var todayMinute = today.getMinutes();
    var todaySecond = today.getSeconds();
    var now = Date.UTC(todayYear,todayMonth,todayDate,todayHour,todayMinute,todaySecond);
    var diff = now - birthDay;
    var diffYears = Math.floor(diff/years);
    var diffDays = Math.floor((diff/days)-diffYears*365);
    var diffHours = Math.floor((diff-(diffYears*365+diffDays)*days)/hours);
    var diffMinutes = Math.floor((diff-(diffYears*365+diffDays)*days-diffHours*hours)/minutes);
    var diffSeconds = Math.floor((diff-(diffYears*365+diffDays)*days-diffHours*hours-diffMinutes*minutes)/seconds);
      document.getElementById('showDays').innerHTML=""+diffYears+" 年 "+diffDays+" 天 "+diffHours+" 小时 "+diffMinutes+" 分钟 "+diffSeconds+" 秒";
  }, 1000);
</script>
        
<div class="busuanzi-count">
  <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <span class="post-meta-item" id="busuanzi_container_site_uv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-user"></i>
      </span>
      <span class="site-uv" title="总访客量">
        <span id="busuanzi_value_site_uv"></span>
      </span>
    </span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item" id="busuanzi_container_site_pv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="site-pv" title="总访问量">
        <span id="busuanzi_value_site_pv"></span>
      </span>
    </span>
</div>








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  




  
<script src="/js/local-search.js"></script>













  

  

<script>
NexT.utils.loadComments(document.querySelector('#lv-container'), () => {
  window.livereOptions = {
    refer: location.pathname.replace(CONFIG.root, '').replace('index.html', '')
  };
  (function(d, s) {
    var j, e = d.getElementsByTagName(s)[0];
    if (typeof LivereTower === 'function') { return; }
    j = d.createElement(s);
    j.src = 'https://cdn-city.livere.com/js/embed.dist.js';
    j.async = true;
    e.parentNode.insertBefore(j, e);
  })(document, 'script');
});
</script>

</body>
</html>
